package com.holly.unit.deform.util;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.holly.unit.auth.api.SessionManagerApi;
import com.holly.unit.auth.api.constants.AuthConstants;
import com.holly.unit.auth.api.pojo.login.LoginUser;
import com.holly.unit.cache.api.CacheOperatorApi;
import com.holly.unit.deform.context.DeformContext;
import com.holly.unit.jwt.api.JwtApi;
import com.holly.unit.jwt.api.exception.JwtException;
import com.holly.unit.jwt.api.exception.enums.JwtExceptionEnum;
import com.holly.unit.system.api.UserServiceApi;
import com.holly.unit.system.api.exception.SystemModularException;
import com.holly.unit.system.api.exception.enums.user.SysUserExceptionEnum;
import com.holly.unit.system.api.pojo.user.SysUserDTO;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.http.HttpServletRequest;

/**
 * 类描述: 编程校验token有效性
 *
 * @author fxr
 * @version 1.0.0
 * @date 2022/4/12 12:53
 */
@Slf4j
public class TokenUtil {

    private static JwtApi jwtApi = DeformContext.jwtApi();

    private static SessionManagerApi sessionManagerApi = DeformContext.sessionManagerApi();

    private static UserServiceApi userServiceApi = DeformContext.userServiceApi();

    private static CacheOperatorApi cacheOperatorApi = DeformContext.defaultStringRedisCacheOperator();

    /**
     * 获取 request 里传递的 token
     *
     * @param request
     * @return
     */
    public static String getTokenByRequest(HttpServletRequest request) {
        String token = request.getParameter("token");
        if (token == null) {
            token = request.getHeader("X-Access-Token");
        }
        return token;
    }

    /**
     * 验证Token
     */
    public static boolean verifyToken(HttpServletRequest request) {
        log.info(" -- url --" + request.getRequestURL());
        String token = getTokenByRequest(request);

        if (StrUtil.isBlank(token)) {
            throw new JwtException(JwtExceptionEnum.JWT_PARSE_ERROR,token);
        }

        // 解密获得username，用于和数据库进行对比
        LoginUser user = sessionManagerApi.getSession(token);
        String username = ObjectUtil.isNull(user)?null:user.getAccount();
        if (username == null) {
            throw new JwtException(JwtExceptionEnum.JWT_PARSE_ERROR,token);
        }

        // 查询用户信息
        SysUserDTO sysUserDTO = userServiceApi.getUserInfoByUserId(user.getUserId());

        if (ObjectUtil.isNull(sysUserDTO)) {
            throw new SystemModularException(SysUserExceptionEnum.USER_NOT_EXIST,user);
        }
        // 判断用户状态
        if (sysUserDTO.getStatusFlag() > 1) {
            throw new SystemModularException(SysUserExceptionEnum.USER_ACCOUNT_LOCK,user);
        }
        // 校验token是否超时失效 & 或者账号密码是否错误
        if (!jwtTokenRefresh(token)) {
            throw new JwtException(JwtExceptionEnum.JWT_EXPIRED_ERROR,token);
        }
        return true;
    }

    /**
     * 刷新token（保证用户在线操作不掉线）
     * @param token
     * @return
     */
    private static boolean jwtTokenRefresh(String token) {
        boolean flag = jwtApi.validateToken(token) && !jwtApi.validateTokenIsExpired(token);
        if (flag) {
            cacheOperatorApi.put(AuthConstants.LOGGED_TOKEN_PREFIX,token,AuthConstants.DEFAULT_AUTH_JWT_TIMEOUT_SECONDS);
        }
        return flag;
    }

}
